<?php

namespace App\Controller;

use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\PostMapping;
use Psr\Http\Message\UploadedFileInterface;
use Hyperf\HttpServer\Contract\RequestInterface;

/**
 * 统一的文件上传控制器
 * 作者 薛原
 * 文件上传其实不应该使用这种方式,一是没有做分片，另一个hyperf为专用的业务处理通道不应该和文件上传这些基础业务共用。
 * Class FileUploadController
 * @package App\Controller
 */
#[Controller(prefix: "/api/file")]
class FileUploadController extends AbstractController
{
    static array $scene = [
        'image'=>['jpg','png'],
        'file' =>["*"]
    ];

    #[PostMapping("upload")]
    public function upload(RequestInterface $request): array|\Psr\Http\Message\ResponseInterface
    {
        // 获取上传的文件
        /** @var UploadedFileInterface[] $uploadedFiles */
        $uploaded_files = $request->getUploadedFiles();
        $file = $uploaded_files['file']; // 假设你的表单字段名为 'file'
        $scene = $request->input("scene","image");
        if ($file instanceof UploadedFileInterface) {
            if(!in_array($scene,array_keys(self::$scene))){
                return $this->fail(40002,"请求失败",["errors"=>"scene参数有误"]);
            }
            $file_name = $file->getClientFilename();
            $check_result = $this->checkExt($scene,$file_name);
            if(!$check_result){
                return $this->fail(40002,"请求失败",["errors"=>"格式有误"]);
            }
            $file_name = $this->rewriteFileName($file_name);
            $file_path = date('Ymd') . '/' . $file_name; // 定义文件存储路径和文件名
            $destination_path = BASE_PATH . '/uploads/' . $file_path; // 定义实际存储路径
            $visit_path = '/uploads/' . $file_path; // 定义访问路径

            // 确保目录存在
            if (!is_dir(dirname($destination_path))) {
                mkdir(dirname($destination_path), 0777, true);
            }

            // 移动文件到指定目录
            $file->moveTo($destination_path);

            return $this->success(["url"=>$visit_path],"success",);
        } else {
            return $this->fail(40002,"请求失败");
        }
    }

    /**
     * 检测文件格式，这里写的粗糙，按照正规还有fileinfo检测等
     * @param $scene
     * @param $file_name
     * @return bool
     */
    private function checkExt($scene, $file_name)
    {
        $ext = $this->getExt($file_name);
        $allow_ext = self::$scene[$scene];
        if(in_array("*",$allow_ext)){
            return true;
        }
        if(in_array($ext,$allow_ext)){
            return true;
        }
        return false;
    }

    /**
     * 获取文件扩展名
     * @param $file_name
     * @return mixed|string
     */
    private function getExt($file_name)
    {
        $mid = explode(".",$file_name);
        $ext = "";
        if(count($mid) != 1){
            $ext = $mid[count($mid) - 1];
        }
        return $ext;
    }

    /**
     * 通过算法重新生成数字型文件名
     * @param $file_name
     * @return mixed|string
     */
    private function rewriteFileName($file_name)
    {
        $ext = $this->getExt($file_name);
        $new_name = date("YmdHis").rand(100000,999999);
        if($ext){
            $file_name = $new_name.".".$ext;
        }
        return $file_name;
    }
}
